package com.android.corestat.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.os.Environment;
import android.text.TextUtils;

/**
 * 类说明：
 * 
 * @author Baker.li
 * @date 2014年4月21日
 * @version 1.0
 */

public class StatUtils {
	private static final String PKGSEQ = "pkgseq";
	
	private static final String UNINSTALL = "uninstall";   //统计程序安装状态是否可以卸载. 1-可卸载, 0-不可卸载
	private static final String TIMESTAMP = "timestamp";   //客户端记录数据产生时的时间戳,取: System.currentTimeMillis()
	private static final String ANDROIDID = "android_id";  //AndroidID
	
	private static final String APPVERSION = "app_version";  //"应用程序版本号",
	private static final String COREVERSION = "core_version";  //"核心统计数据包版本号",
	
	private static final String IMEI = "imei";
	
	private static final String CHANNEL = "channel";   //"渠道号",
	private static final String BRAND = "brand";    //"手机品牌",  
			
	private static final String MODEL = "model";
	private static final String IMSI = "imsi";
	private static final String MAC = "mac";
	private static final String TFCARD = "tfcard";
	/** 操作系统版本 */
	private static final String OSVER = "osver";
	/** ROM容量字节数" */
	private static final String ROMSIZE = "romsize";
	/** ROM容量剩余字节数 */
	private static final String ROMFREE = "romfree";
	/** RAM容量字节数 */
	private static final String RAMSIZE = "ramsize";
	/** RAM容量剩余字节数 */
	private static final String RAMFREE = "ramfree";
	/** 手机联网类型，如：wifi/gprs */
	private static final String NETTYPE = "nettype";

	private static final String APKS = "apks";
	private static final String NAME = "name";
	private static final String MD5 = "md5";
	
	/** 安装信息读取来源：  1-从APK， 2-从SD卡，3-从cust分区， 4-从system分区 */
	private static final String INSTALL_FROM = "install_from";
	private static final String INSTALL_USER = "install_user";
	private static final String INSTALL_CHANNEL = "install_channel";
	private static final String INSTALL_TIME = "install_time";
	private static final String INSTALL_APKS = "install_apks";
	
	private static String INSTALL_INFO_HIDE_FILE_NAME = ".installed";
	private static String INSTALL_INFO_TMP_FILE_NAME = "installed_tmp";
	
	private static String FLASH_CHANNEL_CUST_FILE_PATH = "/cust/.installed";
	private static String FLASH_CHANNEL_SYSTEM_FILE_PATH = "/system/.installed";
	private static String FLASH_INSTALL_INFO_FILE_PATH = "/system/etc/installapplist";
	
	private static int CORE_VERSION = 3; // 统计程序版本号，从1开始。
	
	public static JSONObject createStat(Context context, int index) {
		JSONObject obj = new JSONObject();
		try {
			obj.put(PKGSEQ, index);
			
			if(ApkUtils.packageIsSystemApk(context, context.getPackageName())){
				obj.put(UNINSTALL, "0");
			}else{
				obj.put(UNINSTALL, "1");
			}
			
			obj.put(TIMESTAMP, System.currentTimeMillis());
			obj.put(ANDROIDID, Utils.getAndroidId(context));
			
			obj.put(APPVERSION, Utils.getVersionCode(context));
			obj.put(COREVERSION, CORE_VERSION);
			
			//以第一次获取的imei为准
			String imei = CSPrefs.getImei(context);
			if (TextUtils.isEmpty(imei)) {
				imei = Utils.getIMEI(context);
				CSPrefs.setImei(context, imei);
			}
			obj.put(IMEI, imei);
			
			obj.put(CHANNEL, Utils.getChannelNumber(context));
			obj.put(BRAND, Utils.getBrandName());
			
			obj.put(MODEL, Utils.getModelName());
			obj.put(IMSI, Utils.getIMSI(context));
			obj.put(MAC, Utils.getMacAddress(context));
			obj.put(TFCARD, Utils.getExternalStorageSize());
			obj.put(OSVER, Utils.getOSVersion());
			long[] rom = MemUtils.getRomInfo();
			obj.put(ROMSIZE, String.valueOf(rom[0]));
			obj.put(ROMFREE, String.valueOf(rom[1]));
			long[] ram = MemUtils.getRamInfo();
			obj.put(RAMSIZE, String.valueOf(ram[0]));
			obj.put(RAMFREE, String.valueOf(ram[1]));
			obj.put(NETTYPE, Utils.getNetworkInfo(context)[0]);
			
			Map<String, String> map = IMEIUtils.getIMEIInfo(context);
			if(map != null && map.size() != 0){
				for(String key : map.keySet()){
					obj.put(key, map.get(key));
				}
			}
			
			JSONObject installInfoObj  = null;
			String installInfoStr = null;
			int installFrom = 0;
			do {
				//sdcard:装机
				installInfoStr = getSdcardInstallInfo(context);
				if (isJson(installInfoStr)) {
					installInfoObj = new JSONObject(installInfoStr);
					installFrom = 2;
					break;
				}
				//cust:刷机
				installInfoStr = getFlashInstallInfo(context, FLASH_CHANNEL_CUST_FILE_PATH, FLASH_INSTALL_INFO_FILE_PATH);
				if (isJson(installInfoStr)) {
					installInfoObj = new JSONObject(installInfoStr);
					installFrom = 3;
					break;
				}
				//system:刷机
				installInfoStr = getFlashInstallInfo(context, FLASH_CHANNEL_SYSTEM_FILE_PATH, FLASH_INSTALL_INFO_FILE_PATH);
				if (isJson(installInfoStr)) {
					installInfoObj = new JSONObject(installInfoStr);
					installFrom = 4;
					break;
				}
				//apk:刷机/装机，刷机渠道号前有#
				installInfoStr = getApkInstallInfo(context);
				if (isJson(installInfoStr)) {
					installInfoObj = new JSONObject(installInfoStr);
					installFrom = 1;
					break;
				}
			} while (false);
			
			if (installInfoObj != null) {
				obj.put(INSTALL_FROM, installFrom);
				obj.put(INSTALL_USER, installInfoObj.get(INSTALL_USER));
				obj.put(INSTALL_CHANNEL, installInfoObj.get(INSTALL_CHANNEL));
				obj.put(INSTALL_TIME, installInfoObj.get(INSTALL_TIME));
				obj.put(INSTALL_APKS, installInfoObj.get(INSTALL_APKS));
				
				JSONArray apks = new JSONArray();
				Set<String> names = ApkUtils.getAllPackageNames(context);
				Set<String> watchSet = new HashSet<String>();
				JSONArray watchArray = obj.getJSONArray(INSTALL_APKS);
				for (int i = 0; i < watchArray.length(); i++) {
					JSONObject item = watchArray.getJSONObject(i);
					watchSet.add(item.getString(NAME));
				}
				
				for (String name : names) {
					if(watchSet == null || !watchSet.contains(name)){
						continue;
					}
					String path = ApkUtils.getApkPath(context, name);
					String md5 = CryptUtil.getFileMD5(path);
					JSONObject item = new JSONObject();
					item.put(NAME, name);
					item.put(MD5, md5);
					CSLog.d("md5", "name:" + name + ",md5:" + md5);
					apks.put(item);
				}
				obj.put(APKS, apks);
			}
			
		} catch (JSONException e) {
			e.printStackTrace();
		}

		return obj;
	}

	private static String getSdcardInstallInfo(Context context) {
		String installInfo = null;
		File sdcardFile = new File(Environment.getExternalStorageDirectory(), INSTALL_INFO_HIDE_FILE_NAME);
		File deFile = context.getFileStreamPath(INSTALL_INFO_TMP_FILE_NAME);
		if (!sdcardFile.exists()) {
			return installInfo;
		}
		
		try {
			DesEncryption.decryptFile(sdcardFile, deFile);
			installInfo = getInstallInfoFromInputStream(new FileInputStream(deFile));
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			deFile.delete();
		}
		
		return installInfo;
	}
	
	public static String getApkInstallInfo(Context context) {
		String installInfo = null;
		File apkFile = new File(ApkUtils.getApkPath(context, context.getPackageName()));
		File deFile = context.getFileStreamPath(INSTALL_INFO_TMP_FILE_NAME);
		
		try {
			ZipFile zip = new ZipFile(apkFile);
			Enumeration<? extends ZipEntry> entries = zip.entries();
			while (entries.hasMoreElements()) {
				ZipEntry entry = entries.nextElement();
				String zipEntryName = entry.getName();
				if (entry.isDirectory()) {
					continue;
				}
				if ("META-INF/.installed".equals(zipEntryName)) {
					InputStream in = zip.getInputStream(entry);
					OutputStream fos = new FileOutputStream(deFile);
					DesEncryption.decryptFile(in, fos);
					installInfo = getInstallInfoFromInputStream(new FileInputStream(deFile));
					break;
				}
			}
			zip.close();
		} catch (ZipException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			deFile.delete();
		}
		return installInfo;
	}
	
	private static String getFlashInstallInfo(Context context, String channelPath, String installApkPath) {
		String installInfo = null;
		File channelFile = new File(channelPath);
		File installApkFile = new File(installApkPath);
		if (!channelFile.exists() || !installApkFile.exists()) {
			return null;
		}
		
		try {
			String channelStr = getInstallInfoFromInputStream(new FileInputStream(channelFile));
			String installApkStr = getInstallInfoFromInputStream(new FileInputStream(installApkFile));
			JSONObject channelObj = new JSONObject(channelStr); 
			JSONObject installApkObj = new JSONObject(installApkStr);
			
			CSLog.d("getFlashInstallInfo", "channelStr=" + channelStr);
			CSLog.d("getFlashInstallInfo", "installApkStr=" + installApkStr);
			channelObj.put("install_apks", installApkObj.getJSONArray("install_apks"));
			installInfo = channelObj.toString();
			CSLog.d("getFlashInstallInfo", "installInfo=" + installInfo);
		} catch (Exception e) {
			e.printStackTrace();
		} 
		
		return installInfo;
	}
	
	private static String getInstallInfoFromInputStream(InputStream fis) {
		StringBuffer sb = new StringBuffer();
		Reader reader = null;
		BufferedReader br = null;
		try {
			reader = new InputStreamReader(fis);
			br = new BufferedReader(reader);
			String line = null;
			while ((line = br.readLine()) != null) {
				sb.append(line);
			}
		} catch (Exception e) {
			return null;
		} finally {
			try {
				if (br != null) {
					br.close();
				}
				if (reader != null) {
					reader.close();
				}
			} catch (Exception e) {
				// Ignore anything
			}
		}
		return sb.toString();
	}
	
	public static boolean isJson(String value) {
		if (value == null) {
			return false;
		}
		try {
			new JSONObject(value);
		} catch (JSONException e) {
			return false;
		}
		return true;
	}
	
}
